﻿using System.Collections.Generic;
using System.Linq;
using NHibernate;
using NHibernate.Criterion;
using TestBat.IModels.Domain;
using TestBat.IModels.Models;
using TestBat.IModels.Repositories;
using TestBat.Models.Attributes;

namespace TestBat.Models.Models
{
    public class TraineeGroupModel : Model, ITraineeGroupModel
    {
        public TraineeGroupModel(ITraineeGroupRepository traineeGroupRepository, ITraineeRepository traineeRepository)
        {
            this.traineeGroupRepository = traineeGroupRepository;
            this.traineeRepository = traineeRepository;
        }

        [Conversation]
        public IList<ITraineeGroup> GetAll()
        {
            return traineeGroupRepository.GetAllOrderedBy("Name", true);
        }

        [Conversation(ConversationEndMode.CommitAndContinue)]
        public void Save(ITraineeGroup traineeGroup)
        {
            Validate(traineeGroup);

            traineeGroupRepository.MakePersistent(traineeGroup);
        }

        [Conversation(ConversationEndMode.CommitAndContinue)]
        public void Delete(ITraineeGroup traineeGroup)
        {
            // remove trainee's relation
            foreach (ITrainee trainee in traineeGroup.Trainees)
            {
                trainee.TraineeGroups.Remove(traineeGroup);
                traineeRepository.MakePersistent(trainee);
            }
            traineeGroup.Trainees.Clear();

            traineeGroupRepository.MakeTransient(traineeGroup);
        }

        [Conversation]
        public void Revert(ITraineeGroup traineeGroup)
        {
            traineeGroupRepository.Refresh(traineeGroup);
        }

        [Conversation]
        public IList<ITrainee> GetTrainees(ITraineeGroup traineeGroup)
        {
            DetachedCriteria c = DetachedCriteria.For<ITraineeGroup>()
                .SetFetchMode("Trainees", FetchMode.Eager)
                .Add(Expression.Eq("ID", traineeGroup.ID));
            return (from tg in traineeGroupRepository.GetByCriteria<ITraineeGroup>(c).First<ITraineeGroup>().Trainees orderby tg.Username select tg).ToList<ITrainee>();
        }

        [Conversation]
        public IList<ITraineeGroup> GetAllAvailable(ITrainee trainee)
        {
            return (from tg in traineeGroupRepository.GetAll() where (from tg2 in trainee.TraineeGroups where tg2 == tg select tg2).Count<ITraineeGroup>() == 0 select tg).ToList<ITraineeGroup>();
        }

        [Conversation]
        public IList<ITraineeGroup> GetAllAssociated(ITrainee trainee)
        {
            return trainee.TraineeGroups.ToList<ITraineeGroup>();
        }

        private readonly ITraineeGroupRepository traineeGroupRepository;
        private readonly ITraineeRepository traineeRepository;
    }
}
